/********************************Copyright (c)**********************************\
**
**                   (c) Copyright 2024, Main, China, QD.
**                           All Rights Reserved
**
**                                 By(wo4fisher)
**                           http://www.wo4fisher.com
**
**----------------------------------文件信息------------------------------------
** 文件名称: myiic.c
** 创建人员: wht
** 创建日期: 2024-07-30
** 文档描述: 
**
**----------------------------------版本信息------------------------------------
** 版本代号: V0.1
** 版本说明: 初始版本
**
**------------------------------------------------------------------------------
\********************************End of Head************************************/

#include "myiic.h"

void myiic_Init(void)
{

  GPIO_InitTypeDef GPIO_InitStruct = {0};

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOC_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOC, GPIO_PIN_10|GPIO_PIN_11, GPIO_PIN_SET);

  /*Configure GPIO pins : PDPin PDPin PDPin PDPin */
  GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
  HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
}

void I2C_SDA_OUT(void)//SDA输出方向配置
{
   GPIO_InitTypeDef GPIO_InitStruct = {0};	
  GPIO_InitStruct.Pin = GPIO_PIN_11;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
  HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);						
}

void I2C_SDA_IN(void)//SDA输入方向配置
{
	GPIO_InitTypeDef GPIO_InitStructure;	

	GPIO_InitStructure.Pin=GPIO_PIN_11;
	GPIO_InitStructure.Speed=GPIO_SPEED_FREQ_VERY_HIGH;
	GPIO_InitStructure.Mode=GPIO_MODE_INPUT;
	GPIO_InitStructure.Pull = GPIO_PULLUP;//SCL上拉输入
	HAL_GPIO_Init(GPIOC,&GPIO_InitStructure);
}

#define IIC_DELAY_TIME 5
#define IIC_WAIT_ACK_TIME 100

/**
 * @brief IIC延时
 * @param  无
 * @return 无
 */
void __IIC_Delayus(volatile uint16_t time) {
    uint16_t i = time, j; // 用户根据自己的MCU时钟进行设置倍数

    while ( i-- )
    {
        for(j=5;j>0;j--)
        __NOP();
    }
}

void IIC_start()	//起始信号
{
	I2C_SDA_OUT();
    IIC_SDA_H();
    IIC_SCL_H();
    __IIC_Delayus( IIC_DELAY_TIME);
    IIC_SDA_L();
    __IIC_Delayus( IIC_DELAY_TIME);
    IIC_SCL_L();
}

void IIC_stop()		//终止信号
{
	I2C_SDA_OUT();
    IIC_SCL_L();
    IIC_SDA_L();
    IIC_SCL_H();
    __IIC_Delayus(IIC_DELAY_TIME);
    IIC_SDA_H();
    __IIC_Delayus(IIC_DELAY_TIME);
}

//主机产生一个应答信号
void IIC_ack()
{
	IIC_SCL_L();
	I2C_SDA_OUT();
    __IIC_Delayus( IIC_DELAY_TIME);
    IIC_SDA_L();
    __IIC_Delayus( IIC_DELAY_TIME);
    IIC_SCL_H();
    __IIC_Delayus( IIC_DELAY_TIME);
    IIC_SCL_L();	
}

//主机不产生应答信号
void IIC_noack()
{
	IIC_SCL_L();	
	I2C_SDA_OUT();
    __IIC_Delayus( IIC_DELAY_TIME);
    IIC_SDA_H();
    __IIC_Delayus( IIC_DELAY_TIME);
    IIC_SCL_H();
    __IIC_Delayus( IIC_DELAY_TIME);
    IIC_SCL_L();
}

//等待从机应答信号
//返回值：1 接收应答失败
//		  0 接收应答成功
uint8_t IIC_wait_ack()
{
    uint16_t wait = 0;
//    Soft_IIC_Output();//释放SDA
//    IIC_SDA_H();      //释放SDA
    I2C_SDA_IN(); //转为输入
    IIC_SCL_H();      //释放SCL
    __IIC_Delayus( IIC_DELAY_TIME);
    while ( HAL_GPIO_ReadPin( GPIOC, IIC_SDA_PIN ) == GPIO_PIN_SET)
    {
        wait++;       //加入超时
        if ( wait > IIC_WAIT_ACK_TIME ) //250
        {
            IIC_stop();       //是否有必要停？
            return 0;
        }
    }
    IIC_SCL_L();
    return 1;
}
/**
 * @brief IIC写数据1
 * @param  无
 * @return 无
 */
void Soft_IIC_Write_High(void) {
    IIC_SCL_L();
    IIC_SDA_H();
    __IIC_Delayus( IIC_DELAY_TIME);
    IIC_SCL_H();
    __IIC_Delayus( IIC_DELAY_TIME);
    IIC_SCL_L();
//      __IIC_Delayus ( IIC_DELAY_TIME );
}

/**
 * @brief IIC写数据0
 * @param  无
 * @return 无
 */
void Soft_IIC_Write_Low(void) {
    IIC_SCL_L();
    IIC_SDA_L();
    __IIC_Delayus( IIC_DELAY_TIME);
    IIC_SCL_H();
    __IIC_Delayus( IIC_DELAY_TIME);
    IIC_SCL_L();
    __IIC_Delayus( IIC_DELAY_TIME);
}

void IIC_send_byte(uint8_t txd)
{
	uint8_t i=0;
	I2C_SDA_OUT();
	
	IIC_SCL_L(); //拉低时钟开始数据传输
    for (i = 0x80; i != 0; i >>= 1) {
        if (txd & i) {
            Soft_IIC_Write_High();
        } else {
            Soft_IIC_Write_Low();
        }
    }
}

//读取一个字节
uint8_t IIC_read_byte(uint8_t ack)
{
	uint8_t data = 0, i;
	I2C_SDA_IN();
	
for (i = 0x80; i != 0; i >>= 1)       //高位在前
            {
        IIC_SCL_L();
        __IIC_Delayus( IIC_DELAY_TIME);
        IIC_SCL_H();
        __IIC_Delayus( IIC_DELAY_TIME);
        if (HAL_GPIO_ReadPin( GPIOC, IIC_SDA_PIN ) == GPIO_PIN_SET) {
            data |= i;
        }
        __IIC_Delayus( IIC_DELAY_TIME);
    }
    if (ack) {
        IIC_ack();
    } else {
        IIC_noack();
    }
    return data;
}


/********************************End of File************************************/

